#include "drv_adc.h"
#include "mm32f327xx_hal_config.h"

static void Drv_ADC_GPIO_Config(void)
{
    ADC_GPIO_CLK_EN();
    
    GPIO_Init_Type gpio_init;
    gpio_init.Pins      = ADC_PIN;
    gpio_init.PinMode   = GPIO_PinMode_In_Analog;
    gpio_init.Speed     = GPIO_Speed_50MHz;
    GPIO_Init(ADC_PORT, &gpio_init);
}

static void Drv_ADC_Config(void)
{
    ADC_CLK_EN();
    
    /* setup the converter. */
    ADC_Init_Type adc_init;
    adc_init.Resolution = ADC_Resolution_12b;
    adc_init.ClockDiv   = ADC_ClockDiv_16;
    adc_init.ConvMode   = ADC_ConvMode_SingleSlot;
    adc_init.Align      = ADC_Align_Right;
    ADC_Init(ADC_INSTANCE, &adc_init);

    ADC_Enable(ADC_INSTANCE, true); /* power on the converter. */
    ADC_EnableTempSensor(ADC_INSTANCE, true); /* enable the temperature sensor. */

    /* setup the sequence, a regular conversion with only one channel. */
    ADC_RegSeqConf_Type adc_regseq_conf;
    adc_regseq_conf.SeqSlots        = 1u << ADC_CH;
    adc_regseq_conf.SeqDirection    = ADC_RegSeqDirection_LowFirst;
    ADC_EnableRegSeq(ADC_INSTANCE, &adc_regseq_conf);

    /* set channel sample time. */
    ADC_SetChnSampleTime(ADC_INSTANCE, ADC_CH, ADC_SampleTime_Alt7);
}

void Drv_ADC_Init(void)
{
    Drv_ADC_GPIO_Config();
    Drv_ADC_Config();
}

unsigned int Drv_ADC_GetDigitalValue(void)
{
    uint32_t data;
    uint32_t flags;
    uint32_t adc_channel; /* keep the actual hardware conversion channel number. */
    
    /* software tirgger the conversion. */
    ADC_DoSwTrigger(ADC_INSTANCE, true);

    /* wait while the conversion is ongoing. */
    while( 0u == (ADC_GetStatus(ADC_INSTANCE) & ADC_STATUS_CONV_SEQ_DONE) )
    {}

    ADC_ClearStatus(ADC_INSTANCE, ADC_STATUS_CONV_SEQ_DONE);

    data = ADC_GetConvResult(ADC_INSTANCE, &adc_channel, &flags);

    if (0u == (flags & ADC_CONV_RESULT_FLAG_VALID) )
    {
        data = 0u; /* the data is unavailable when the VALID flag is not on. */
    }

    return data;
}

float Drv_ADC_GetAnalogValue(void)
{
    uint32_t data = Drv_ADC_GetDigitalValue();
    float value = ( (data * VREF / 4096) - V25)/AVG_SLOPE + 25;
    
    return value;
}

